<?php
session_start();
class process {
	public $cmd = '';
	public $full_cmd = '';
	public $state = 0;
	public $result = '';
	public $err = '';
	public $pid = -1;
	public $out_file;
	public $err_file;
	public $time_start;
	public $time_end;
	public $runtime = 0;
}
class processes {
	public $proc = array();
	private $sid = '';
	public $run_cnt = 0;
	function __construct($proc_prefix = 'DEFAULT'){
		$this->sid = 'PID-' . $proc_prefix;
		if (isset($_SESSION[$this->sid])){
			$this->proc = $_SESSION[$this->sid];
			$this->poll_processes();
		}
	}
	function __destruct(){
		$_SESSION[$this->sid] = $this->proc;
	}
	function db_create(){
		global $wapi;
		$stop = '';
	}
	function run($cmd, $wait = -1) {
   		$p = new process();
   		$waited = 0;
   		$p->cmd = $cmd;
   		$p->out_file = $this->get_tmpfile();
   		$p->err_file = $this->get_tmpfile();
		$p->full_cmd = "$cmd 1> $p->out_file 2> $p->err_file < /dev/null & echo " . '$!';
		$p->time_start = date("Y-m-d H:i:s",time());
		$p->state = 1;
		$p->pid = shell_exec($p->full_cmd);
		$this->run_cnt ++;
		$this->proc[$p->pid] = $p;
		if ($wait >= 0) {
			while($this->pid_running($p->pid)) {
				sleep(1);
				$n = date("Y-m-d H:i:s",time());
				$waited = $this->time_diff($p->time_start,$n);
				if ($wait > 0 && $waited >= $wait) {
					break;
				}
			}
			$this->poll_processes();
		}
		return $p;
	}
	function poll_processes(){
		$cnt = 0;
		if (count($this->proc) > 0) {
			foreach ($this->proc as $i => $p){
				if ($p->state == 1) {
					$running = $this->pid_running($p->pid);
					if (!$running) {
						// read and delete the output files
						if (is_file($p->out_file)){
							$p->result = file_get_contents($p->out_file);
							unlink($p->out_file);
						}
						if (is_file($p->err_file)){
							$p->err = file_get_contents($p->err_file);
							unlink($p->err_file);
						}
						$p->time_end = date("Y-m-d H:i:s",time());
						$p->runtime = $this->time_diff($p->time_start,$p->time_end);
						if ($p->err == '') {
							$p->state = 0;
						} else {
							$p->state = -1;
						}
					} else  {
						$cnt ++;
					}
				}
			}
		}
		$this->run_cnt = $cnt;
	}
	function clear_done(){
		if (count($this->proc) > 0) {
			foreach ($this->proc as $i => $p){
				if ($p->state != 1) {
					$this->remove_pid($i);
				}
			}
		}
	}
	function remove_pid($i){
		unset($this->proc[$i]);
	}
	function remove_all(){
		$this->proc = array();
	}
	function pid_running($pid){
		exec("ps $pid", $pstate);
		return(count($pstate) >= 2);
   	}
	function get_tmpfile(){
		$fname = tempnam(sys_get_temp_dir(), 'FOO');
		return $fname;
	}
	function time_diff($firstTime,$lastTime){
		$firstTime = strtotime($firstTime);
		$lastTime = strtotime($lastTime);
		$timeDiff = $lastTime - $firstTime;
		return $timeDiff;
	}
	function show_processes($show_all = false, $clear_done = false){
		echo "Process count: " . $this->run_cnt . " (" . count($this->proc) . ")<br />\n";
		if (count($this->proc) > 0) {
			foreach ($this->proc as $i => $p){
				if ($p->state == 1 || $show_all) {
					$this->show_pid($i);
				}
			}
		}
		if ($clear_done) {
			$this->clear_done();
		}
	}
	function show_pid($i){
		$p = $this->proc[$i];
		echo "Index: " . $i . "<br />\n";
		echo "PID: " . $p->pid . "<br />\n";
		echo "Cmd: " . $p->cmd . "<br />\n";
		echo "Full Cmd: " . $p->full_cmd . "<br />\n";
		echo "State: " . $p->state . "<br />\n";
		echo "Data Cnt: " . strlen($p->result) . "<br />\n";
		echo "Err Cnt: " . strlen($p->err) . "<br />\n";
		echo "Start: " . $p->time_start . "<br />\n";
		echo "End: " . $p->time_end . "<br />\n";
		echo "Runtime: " . $p->runtime . "<br />\n";
		echo "<br />";
	}
}
//unset($_SESSION['PID-PROC']);
$p = new processes();
//$p->run('wget http://192.168.0.130/TVersity_1_9_2_Pro_1.rar',5);
//$p1 = $p->run('cd /private/var/mobile; ls -l',0);
//echo nl2br($p1->result);
$p->show_processes(true);



?>